#include <stdio.h> 
#include <string.h> 
#include <openssl/crypto.h> 
#include <openssl/err.h> 
#include <openssl/rand.h> 
#include <openssl/bn.h> 
#include <openssl/rsa.h> 
#include <openssl/pem.h> 
 
void print(const unsigned char *a, const int l)
{
	printf("\n");
	for(int i = 0; i < l; i ++)
	{
		if(a[i] >= 16)
		{
			printf("%x", a[i]);
		}
		else 
		{
			printf("0%x", a[i]);
		}	
	}
	printf("\n");
}

#define SetKey(method) \
    method(n, key->n); \
	key->e = method(e, sizeof(e), key->e); \
	key->d = method(d, sizeof(d), key->d); \
	key->p = method(p, sizeof(p), key->p); \
	key->q = method(q, sizeof(q), key->q); \
	key->dmp1 = method(dmp1, sizeof(dmp1), key->dmp1); \
	key->dmq1 = method(dmq1, sizeof(dmq1), key->dmq1); \
	key->iqmp = method(iqmp, sizeof(iqmp), key->iqmp); 
 
static int key5(RSA *key) 
{ 
    //密钥中变量  
/*    static unsigned char n[] = {
	0xBE,0x38,0xEA,0x9E,0xD0,0x20,0x87,0xB5,0x8F,0xCF,0x50,0x49,0x30,0x2C,0xDD,0x2F,0x09,0x2C,0x78,0xE8,0x6C,0x09,0x8F,0x82,0xE8,0xC9,0xBA,0x60,0x19,0xA9,0xC1,0x2F,0xCE,0x98,0x7A,0x1B,0xDC,0x3C,0x09,0x3E,0x61,0x18,0xEC,0x46,0x12,0xD7,0x90,0xD2,0x3E,0x02,0x28,0x18,0x75,0xB1,0x52,0xB4,0x7D,0xA3,0xEE,0x12,0x4F,0x12,0xB1,0xB9,0xA7,0x04,0xB0,0x4A,0x89,0x09,0xA4,0x3D,0x22,0xFF,0x59,0x9F,0xB1,0x52,0x14,0x5F,0xDF,0x45,0xC5,0x8A,0xC1,0x0F,0xCB,0x1A,0xB0,0xD2,0x7C,0x56,0xC2,0xA8,0x36,0x77,0x08,0x9F,0xFC,0x0E,0x38,0x4C,0xAC,0x4C,0x2C,0x28,0x6B,0xBA,0x73,0xF6,0x70,0xC8,0xB2,0x1D,0x66,0x04,0xAD,0x76,0x93,0x03,0x2B,0xB7,0x1C,0x17,0xBD,0x64,0x0C,0xF9};
 
    static unsigned char e[] = "\x00\x01\x00\x01"; 
 
    static unsigned char d[] = {
	0x53,0xDF,0x04,0x93,0xC1,0x70,0x96,0x65,0x97,0x62,0xF1,0x23,0x53,0xFA,0x74,0x0B,0xA9,0x1F,0xD2,0xAF,0xA7,0xF3,0x0F,0x33,0xC9,0x30,0x28,0xDC,0xF6,0x73,0xC2,0x9A,0x31,0x9D,0x49,0x39,0xBF,0x81,0x39,0x12,0x27,0xFD,0xB5,0x2F,0xB0,0x5F,0x1B,0x9B,0x97,0x7B,0x9B,0xF2,0x2C,0xF2,0x62,0x64,0xF2,0x80,0xB5,0x17,0x9D,0x85,0xC0,0x96,0x37,0x60,0xDA,0xE0,0xB8,0xC2,0x55,0x01,0x92,0x30,0x5C,0x3D,0x9A,0x32,0x4E,0x01,0xFA,0xDB,0x13,0xBC,0x2F,0xF7,0x55,0x73,0x48,0xB3,0x0A,0x80,0xB5,0x5C,0xB9,0x7B,0xFF,0x62,0xDF,0xD8,0xE5,0x29,0xB7,0x0A,0x58,0x0D,0x5D,0xD7,0xB3,0x4F,0x73,0xB9,0x3A,0x7C,0xB8,0x09,0xE1,0x59,0xB4,0x6F,0x70,0xB9,0xE5,0xE1,0xA0,0xE4,0x25,0x81};
 
    static unsigned char p[] = {
	0xF3,0x9F,0x80,0xA2,0x25,0x81,0x2B,0x5D,0x99,0x3C,0x43,0xCA,0x33,0x53,0xFC,0xAF,0x07,0x00,0x64,0x6C,0x71,0x80,0x8B,0x3F,0x86,0xCD,0x0E,0x65,0x69,0xBD,0x1A,0xB5,0x30,0x73,0xB4,0x32,0x45,0x11,0xB6,0xF9,0x66,0x75,0x4C,0xC3,0xA9,0xEF,0xDE,0x76,0x54,0x6A,0x6C,0x13,0xCA,0x88,0x2A,0x0C,0x53,0x19,0x9D,0x8B,0x7A,0x22,0x67,0x4F};
 
    static unsigned char q[] = {
	0xC7,0xE2,0xE5,0xEF,0x16,0xF6,0x10,0x82,0xC5,0x23,0x58,0xE6,0x4D,0xA8,0x1E,0x99,0x3C,0x5F,0x55,0x01,0x5C,0x6D,0x77,0x0B,0x60,0x1D,0x12,0xC3,0xB4,0x82,0xEE,0xBE,0xCA,0x02,0x0B,0xCB,0x76,0x77,0xA9,0x2A,0xF2,0xD9,0x7B,0x9F,0x9A,0x55,0x9B,0x08,0x87,0xBF,0x00,0xAF,0xBD,0x7A,0x44,0x07,0x3E,0x4F,0x0C,0x56,0x56,0x7B,0xB5,0x37};
 
    static unsigned char dmp1[] = {
	0x18,0x6C,0x43,0x0E,0xFE,0x47,0x86,0xBB,0x69,0x63,0x3B,0x40,0x88,0x08,0xC1,0x6A,0x22,0x7F,0x8D,0x91,0xB9,0x87,0x33,0x6E,0x78,0xEB,0x11,0xA8,0x65,0x03,0x4A,0x2C,0x23,0xE1,0x55,0x8D,0x3C,0x93,0x5C,0x0E,0x80,0x90,0xFD,0xD3,0x17,0xB4,0x2E,0x4F,0x1A,0x83,0x58,0xB6,0x5B,0x35,0x6F,0x51,0xB0,0xFA,0xFE,0x6A,0x3F,0x22,0x37,0xCD}; 

    static unsigned char dmq1[] = {
	0x87,0x9E,0x01,0xA5,0x8B,0x2D,0x9E,0x1C,0x2B,0x87,0x04,0xFD,0x14,0xB9,0x39,0x31,0x7C,0x8D,0xAD,0xCE,0x03,0x98,0xDD,0x89,0x21,0x47,0xF8,0x80,0x41,0xCC,0x08,0x11,0xF8,0x5B,0x15,0x07,0x91,0xB4,0x34,0x59,0xC8,0x75,0x18,0x74,0x3C,0x31,0x52,0xC3,0xA1,0xDE,0x4C,0xA7,0xEF,0xE5,0xB1,0x9C,0x3C,0x81,0x43,0x7C,0x9C,0xA6,0xC8,0x57}; 

    static unsigned char iqmp[] = {
	0xE8,0xCE,0x2F,0xDF,0xC6,0x7A,0x10,0x07,0x18,0xEE,0xD1,0x92,0x56,0x55,0x11,0xA3,0xEB,0x2E,0x2C,0x07,0x3A,0x31,0xD4,0x0C,0x82,0x61,0x40,0x9C,0xA3,0x65,0xB8,0x78,0x44,0xE0,0x18,0xA0,0x15,0xE6,0x09,0xE6,0xFE,0x32,0x54,0xB7,0x7D,0x59,0xCC,0xFE,0x4D,0x28,0xBF,0xCB,0xC2,0x5D,0x7D,0xF7,0x82,0x79,0x99,0x4C,0xC7,0x68,0xBD,0xBE};

*/ 


    static char n[] = "BE38EA9ED02087B58FCF5049302CDD2F092C78E86C098F82E8C9BA6019A9C12FCE987A1BDC3C093E6118EC4612D790D23E02281875B152B47DA3EE124F12B1B9A704B04A8909A43D22FF599FB152145FDF45C58AC10FCB1AB0D27C56C2A83677089FFC0E384CAC4C2C286BBA73F670C8B21D6604AD7693032BB71C17BD640CF9";
 
    static char e[] = "10001"; 
 
    static char d[] = "53DF0493C17096659762F12353FA740BA91FD2AFA7F30F33C93028DCF673C29A319D4939BF81391227FDB52FB05F1B9B977B9BF22CF26264F280B5179D85C0963760DAE0B8C2550192305C3D9A324E01FADB13BC2FF7557348B30A80B55CB97BFF62DFD8E529B70A580D5DD7B34F73B93A7CB809E159B46F70B9E5E1A0E42581";

    static char p[] = "f39f80a225812b5d993c43ca3353fcaf0700646c71808b3f86cd0e6569bd1ab53073b4324511b6f966754cc3a9efde76546a6c13ca882a0c53199d8b7a22674f";

    static char q[] = "c7e2e5ef16f61082c52358e64da81e993c5f55015c6d770b601d12c3b482eebeca020bcb7677a92af2d97b9f9a559b0887bf00afbd7a44073e4f0c56567bb537";

 
    static char dmp1[] = "186c430efe4786bb69633b408808c16a227f8d91b987336e78eb11a865034a2c23e1558d3c935c0e8090fdd317b42e4f1a8358b65b356f51b0fafe6a3f2237cd";

    static char dmq1[] = "879e01a58b2d9e1c2b8704fd14b939317c8dadce0398dd892147f88041cc0811f85b150791b43459c87518743c3152c3a1de4ca7efe5b19c3c81437c9ca6c857";

    static char iqmp[] = "e8ce2fdfc67a100718eed192565511a3eb2e2c073a31d40c8261409ca365b87844e018a015e609e6fe3254b77d59ccfe4d28bfcbc25d7df78279994cc768bdbe";


	char* pt;
	BN_hex2bn(&key->n, n);
	pt = BN_bn2hex(key->n);
	//printf("1:%s\n", pt);
	OPENSSL_free(pt);
	
	BN_hex2bn(&key->e, e);
	pt = BN_bn2hex(key->e);
	//printf("2:%s\n", pt);
	OPENSSL_free(pt);
	
	BN_hex2bn(&key->d, d);
	pt = BN_bn2hex(key->d);
	//printf("3:%s\n", pt);
	OPENSSL_free(pt);
	
	BN_hex2bn(&key->p, p);
	pt = BN_bn2hex(key->p);
	//printf("4:%s\n", pt);
	OPENSSL_free(pt);
	
	BN_hex2bn(&key->q, q);
	pt = BN_bn2hex(key->q);
	//printf("5:%s\n", pt);
	OPENSSL_free(pt);
	 
	BN_hex2bn(&key->dmp1, dmp1);
	pt = BN_bn2hex(key->dmp1);
	//printf("6:%s\n", pt);
	OPENSSL_free(pt);
	
	BN_hex2bn(&key->dmq1, dmq1);
	pt = BN_bn2hex(key->dmq1);
	//printf("7:%s\n", pt);
	OPENSSL_free(pt);
	
	BN_hex2bn(&key->iqmp, iqmp);
	pt = BN_bn2hex(key->iqmp);
	//printf("5:%s\n", pt);
	OPENSSL_free(pt);

	/*char tt[64];
	BIGNUM *t = (BIGNUM*)malloc(sizeof(BIGNUM)) ;
	char *pt;
	pt = BN_bn2hex(t);
	printf("1:%s\n", pt);
	OPENSSL_free(pt);
	BN_one(t);
	pt = BN_bn2hex(t);
	printf("2:%s\n", pt);
	OPENSSL_free(pt);
	BN_dec2bn(&t, "6584");
	pt = BN_bn2hex(t);
	printf("3:%s\n", pt);
	OPENSSL_free(pt);
	BN_hex2bn(&t, "123F23D12");
	pt = BN_bn2hex(t);
	printf("4:%s\n", pt);
	OPENSSL_free(pt);
	free(t);
	t = NULL;*/ 
	
	//printf("sizeof is %lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", sizeof(n),sizeof(e),sizeof(d),sizeof(p),sizeof(q),sizeof(dmp1),sizeof(dmq1),sizeof(iqmp));	
	/*
	print(n, (int)sizeof(n));
	print(d, (int)sizeof(d));
	print(p, (int)sizeof(p));
	print(q, (int)sizeof(q));
	print(dmp1, (int)sizeof(dmp1));
	print(dmq1, (int)sizeof(dmq1));
	print(iqmp, (int)sizeof(iqmp));*/ 
	return 0;
} 

 
int main(int argc, char *argv[]) 
{ 
    int err = 0; 
    int v; 
    RSA *key; 
    unsigned char ptext[1024]; 
    unsigned char ctext[1024]; 
    static unsigned char ptext_ex[1024]; 
    unsigned char ctext_ex[1024]; 
    int plen; 
    int clen = 0; 
    int num; 
    int n; 
    int i; 
    EVP_PKEY *pkey; 
 
    //printf("ptext_ex: %s\n", ptext_ex); 
    memset(ptext_ex, 0, 1024);
	ptext_ex[1023] = 2;
	{ 
        key = RSA_new(); 
        key5(key); 
 
        plen = sizeof(ptext_ex) - 1; 
        num = RSA_private_encrypt(plen, ptext_ex, ctext, key, 
                RSA_NO_PADDING); 
        if (num != 128)   //模数长度  
        { 
            printf("PKCS#1 v1.5 encryption failed! num = %d\n", num); 
            err=1; 
            goto next; 
        } 
 
        //加密后的数据  
        printf("encrypted text: \n"); 
        for (i = 0; i < num; i++) 
        { 
            printf("%02x", ctext[i]); 
        } 
        printf("\n"); 
 
        printf("RSA_private_encrypt num: %d\n", num); 
 
        num = RSA_public_decrypt(num, ctext, ptext, key, 
                RSA_NO_PADDING); 
        if (num != plen || memcmp(ptext, ptext_ex, num) != 0) 
        { 
            printf("PKCS#1 v1.5 decryption failed!\n"); 
            err=1; 
        } 
        else 
            printf("PKCS #1 v1.5 encryption/decryption ok\n"); 
 
        printf("RSA_public_decrypt num: %d\n", num); 
        ptext[num] = '\0';    //字符串结尾 
        printf("ptext: %s\n", ptext); 
		


    	printf("2nd::::ptext_ex: %s\n", ptext_ex); 
 		strcpy((char*)ptext_ex, (const char*)ptext);
        plen = sizeof(ptext_ex) - 1; 
        num = RSA_public_encrypt(plen, ptext_ex, ctext, key, 
                RSA_NO_PADDING); 
        if (num != 128)   //模数长度  
        { 
            printf("PKCS#1 v1.5 encryption failed! num = %d\n", num); 
            err=1; 
            goto next; 
        } 
 
        //加密后的数据  
        printf("encrypted text: \n"); 
        for (i = 0; i < num; i++) 
        { 
            printf("%02x", ctext[i]); 
        } 
        printf("\n"); 
 
        printf("RSA_private_encrypt num: %d\n", num); 
 
        num = RSA_private_decrypt(num, ctext, ptext, key, 
                RSA_NO_PADDING); 
        if (num != plen || memcmp(ptext, ptext_ex, num) != 0) 
        { 
            printf("PKCS#1 v1.5 decryption failed!\n"); 
            err=1; 
        } 
        else 
            printf("PKCS #1 v1.5 encryption/decryption ok\n"); 
 
        printf("RSA_public_decrypt num: %d\n", num); 
        ptext[num] = '\0';    //字符串结尾 
        printf("ptext: %s\n", ptext); 
next: 
        //公钥和私钥输出为 PEM 格式： 
        PEM_write_RSAPrivateKey(stdout, key, NULL, NULL, 0, NULL, NULL); 
        PEM_write_RSAPublicKey(stdout, key); 

		/*FILE *fp = fopen("./private.pem", "wb");
		FILE *fp2 = fopen("./public.pem", "wb");
        PEM_write_RSAPrivateKey(fp, key, NULL, NULL, 0, NULL, NULL); 
        PEM_write_RSAPublicKey(fp2, key); */ 
	
		
		int ret;
		BIO *out;
   		out = BIO_new_file("./private.pem","w");
    	//这里生成的私钥没有加密，可选加密
    	ret = PEM_write_bio_RSAPrivateKey(out, key, NULL, NULL, 0, NULL, NULL);
		BIO_flush(out);
		BIO_free(out); 

   		out = BIO_new_file("./public.pem","w");
    	//这里生成的私钥没有加密，可选加密
    	ret = PEM_write_bio_RSAPublicKey(out, key);

		BIO_flush(out);
		BIO_free(out); 
        
		//释放申请的内存 
        RSA_free(key); 
    } 
 
    if (err) printf("ERROR: %d\n", err); 
    return err; 
} 
